BOOTSTRAP_METHODS = "BootstrapMethods"
LINE_NUMBER_TABLE = "LineNumberTable"
CODE = "Code"
CONSTANT_VALUE = "ConstantValue"
DEPRECATED = "Deprecated"
ENCLOSING_METHOD = "EnclosingMethod"
EXCEPTIONS = "Exceptions"
INNER_CLASSES = "InnerClasses"
LOCAL_VARIABLE_ABLE = "LocalVariableTable"
LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable"
SIGNATURE = "Signature"
SOURCE_FILE = "SourceFile"
SYNTHETIC = "Synthetic"
UN_PARSED = "UnParsed"
RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"
RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTRIBUTE = "RuntimeVisibleParameterAnnotationsAttribute"
ANNOTATION_DEFAULT = "AnnotationDefault"


class AttributeInfo:
    def __init__(self):
        self.type = None

    def readInfo(self, clsReader):
        pass

    def setType(self, typ):
        self.type = typ
        return self

    @staticmethod
    def readAttributes(reader, constPool):
        attrCount = int.from_bytes(reader.readU16(), "big")
        attrs = []
        for i in range(attrCount):
            attrs.append(AttributeInfo.readAttribute(reader, constPool))
        return attrs

    @staticmethod
    def readAttribute(reader, constPool):
        attrNameIndex = int.from_bytes(reader.readU16(), "big")
        attrName = constPool.getUTF8(attrNameIndex)
        attrLen = int.from_bytes(reader.readU32(), "big")
        attrInfo = AttributeInfo.newAttributeInfo(attrName, attrLen, constPool)
        attrInfo.readInfo(reader)
        return attrInfo

    @staticmethod
    def newAttributeInfo(attrName, attrLen, constPool):
        from classfile.attr_bootstrap_methods import BootstrapMethodsAttribute
        from classfile.attr_code import CodeAttribute
        from classfile.attr_constant_value import ConstantValueAttribute
        from classfile.attr_enclosing_method import EnclosingMethodAttribute
        from classfile.attr_exceptions import ExceptionsAttribute
        from classfile.attr_inner_class import InnerClassesAttribute
        from classfile.attr_line_number_table import LineNumberTableAttribute
        from classfile.attr_local_variable_table import LocalVariableTableAttribute
        from classfile.attr_local_variable_type_table import LocalVariableTypeTableAttribute
        from classfile.attr_makers import DeprecatedAttribute, SyntheticAttribute
        from classfile.attr_signature import SignatureAttribute
        from classfile.attr_source_file import SourceFileAttribute
        from classfile.attr_unparsed import UnParsedAttribute

        attr = None

        if attrName == BOOTSTRAP_METHODS:
            attr = BootstrapMethodsAttribute()
        elif attrName == CODE:
            attr = CodeAttribute(constPool)
        elif attrName == CONSTANT_VALUE:
            attr = ConstantValueAttribute()
        elif attrName == DEPRECATED:
            attr = DeprecatedAttribute()
        elif attrName == ENCLOSING_METHOD:
            attr = EnclosingMethodAttribute(constPool)
        elif attrName == EXCEPTIONS:
            attr = ExceptionsAttribute()
        elif attrName == INNER_CLASSES:
            attr = InnerClassesAttribute()
        elif attrName == LINE_NUMBER_TABLE:
            attr = LineNumberTableAttribute()
        elif attrName == LOCAL_VARIABLE_TYPE_TABLE:
            attr = LocalVariableTypeTableAttribute()
        elif attrName == LOCAL_VARIABLE_ABLE:
            attr = LocalVariableTableAttribute()
        elif attrName == SIGNATURE:
            attr = SignatureAttribute(constPool)
        elif attrName == SOURCE_FILE:
            attr = SourceFileAttribute(constPool)
        elif attrName == SYNTHETIC:
            attr = SyntheticAttribute()
        else:
            attr = UnParsedAttribute(attrName, attrLen)
            attr.setType(UN_PARSED)
            return attr
        attr.setType(attrName)
        return attr
